package com.maas.util.mybatis.jpa.littlenb.support.template.select;

import com.littlenb.mybatisjpa.support.Constant;
import com.littlenb.mybatisjpa.support.template.SqlTemplate;
import com.littlenb.mybatisjpa.util.ColumnMetaResolver;
import com.littlenb.mybatisjpa.util.PersistentUtil;
import com.maas.util.mybatis.jpa.littlenb.common.JpaTools;
import com.maas.util.mybatis.jpa.littlenb.common.MyColumnMetaResolver;
import com.maas.util.mybatis.jpa.littlenb.common.db.JbaDbPluginConst;
import com.maas.util.mybatis.jpa.littlenb.common.type.OperateEnum;
import org.apache.commons.lang3.ArrayUtils;

import java.lang.reflect.Field;

/**
 * 不穿空值
 * 动态生成<where>，还没实现, 不能为空
 * SelectCertainSqlTemplate
 * @author sway.li
 **/
public class SelectCertainSqlTemplate implements SqlTemplate {

  public static final SelectCertainSqlTemplate INSTANCE = new SelectCertainSqlTemplate();
  public String[] neFeildArr =null;
  public String[] likeFeildArr =null;

  public String[] emptyEqFeildArr =null;

  public String where ="";


  public String[] dateParmArr =null;

  public String[] dateSearchArr =null;



  public String parseSQLEx(Class<?> type,String certainName) {
    // columns
    StringBuilder sets = new StringBuilder();
    String certainNamePre ="";
    if(!JpaTools.isEmpty(certainName)){
      certainNamePre =certainName  +".";
    }

    if(JpaTools.isNotEmpty(where)){
      sets.append(  " where " + where);
    }else {
      sets.append("<trim prefix=\"WHERE\" prefixOverrides=\"AND\">");

      //PersistentUtil.getPersistentFields
      Field[] fieldArr =PersistentUtil.getDeclaredFields(type);
      for (Field field : fieldArr) {
        /**
         * includes： 传入的includes 字符串数组
         * certainName： 传入的查询对象一般为certainty.
         * 是否查这个字段：includes 包含该字段 且 certainty 包含该字段
         * 生成的查询:字段 + 运算符 + 值
         */
        if(inDateParm(field.getName())){
          /**
           * 日期查询
           */
          String sqlOracleXml =resolveDateSql(field);
          String columnName =PersistentUtil.getColumnName(field);
          int parmIndex  = indexOfDateParm(field.getName());

          String[] oneDateSearchArr= getDateSearchParm(parmIndex);


          String bdateParm =certainNamePre+Constant.CERTAINTY_ENTITY_KEY+"."+oneDateSearchArr[0];
          String edateParm =certainNamePre+Constant.CERTAINTY_ENTITY_KEY+"."+oneDateSearchArr[1];
          sqlOracleXml=sqlOracleXml.replaceAll("\\$\\{columnName\\}",columnName)
                  .replaceAll("\\$\\{bdate\\}",bdateParm)
                  .replaceAll("\\$\\{edate\\}",edateParm);

          sets.append(sqlOracleXml);
        }
        else if(inEmptyEqFeildArr(field.getName())){
          //includes 包含该字段 且 certainty 包含该字段
          sets.append(String.format(
                  "<if test='"+certainNamePre+"includes.contains(\"%1$s\") and !"+certainNamePre+"excludes.contains(\"%1$s\")'> ",
                  field.getName()
          ));
          // columnName = #{ }

          sets.append("and ");



          // 字段 + 运算符 + 值
          sets.append("nvl("+PersistentUtil.getColumnName(field)+",0)" )

                  .append(" "+ OperateEnum.EQUAL.getOperate()+" ")
                  .append(ColumnMetaResolver.resolveSqlPlaceholder(field, certainNamePre+Constant.CERTAINTY_ENTITY_KEY));

          sets.append("</if> ");
        }
        else if(inNeFeildArr(field.getName())){
          //不等于
          sets.append(String.format(
                  "<if test='"+certainNamePre+"includes.contains(\"%1$s\") and !"+certainNamePre+"excludes.contains(\"%1$s\")'> ",
                  field.getName()
          ));
          // columnName = #{ }

          sets.append("and ");
          sets.append(PersistentUtil.getColumnName(field)).append(" "+ OperateEnum.NOT.getOperate()+" ")
                  .append(ColumnMetaResolver.resolveSqlPlaceholder(field, certainNamePre+Constant.CERTAINTY_ENTITY_KEY));

          sets.append("</if> ");
        }else if(inLikeFeildArr(field.getName())){
          //不等于
          sets.append(String.format(
                  "<if test='"+certainNamePre+"includes.contains(\"%1$s\") and !"+certainNamePre+"excludes.contains(\"%1$s\")'> ",
                  field.getName()
          ));
          // columnName = #{ }

          sets.append("and ");
          sets.append(PersistentUtil.getColumnName(field)).append(" "+ OperateEnum.LIKE.getOperate()+" ");
          sets.append(MyColumnMetaResolver.resolveSqlLike(field, certainNamePre+Constant.CERTAINTY_ENTITY_KEY));

          sets.append("</if> ");
        }else{
          //等于
          sets.append(String.format(
                  "<if test='"+certainNamePre+"includes.contains(\"%1$s\") and !"+certainNamePre+"excludes.contains(\"%1$s\")'> ",
                  field.getName()
          ));
          // columnName = #{ }

          sets.append("and ");
          sets.append(PersistentUtil.getColumnName(field)).append(" = ")
                  .append(ColumnMetaResolver.resolveSqlPlaceholder(field, certainNamePre+Constant.CERTAINTY_ENTITY_KEY));

          sets.append("</if> ");
        }
      }

      sets.append("</trim> ");
    }


    return sets.toString();
  }


  /**
   * 日期查询语句
   * @param field
   * @return
   */
  public static String resolveDateSql(Field field) {
    if(JbaDbPluginConst.DIALECT_CURR.equals(JbaDbPluginConst.DIALECT_KINGBASE_V8)||JbaDbPluginConst.DIALECT_CURR.equals(JbaDbPluginConst.DIALECT_ORACLE) ){
      String sqlOracleXml ="\t<if test=\"${bdate}!=null and ${bdate}!=''\">\n" +
              "\t\t\t\t\t\t<![CDATA[\n" +
              "\t\t\t\t\t\t\tand to_char(${columnName},'yyyy-mm-dd')>=#{${bdate}}\n" +
              "\t\t\t\t\t\t]]>\n" +
              "\t\t\t</if>\n" +
              "\t\t\t<if test=\"${bdate}!=null and ${bdate}!=''\">\n" +
              "\t\t\t\t\t\t<![CDATA[\n" +
              "\t\t\t\t\t\t\tand to_char(${columnName},'yyyy-mm-dd')<=#{${edate}}\n" +
              "\t\t\t\t\t\t]]>\n" +
              "\t\t\t</if> ";
      return sqlOracleXml;
    }else if(JbaDbPluginConst.DIALECT_CURR.equals(JbaDbPluginConst.DIALECT_MYSQL)){
      //return resolveSqlLikeMySql( field,  alias);
    }else {
      //return resolveSqlLikeOther( field,  alias);
    }
    return "";
  }

  @Override
  public String parseSQL(Class<?> type) {
    return parseSQLEx(type,"");
  }



  public String parseSQL_Old(Class<?> type) {
    // columns
    StringBuilder sets = new StringBuilder();
    sets.append("<trim prefix=\"WHERE\" prefixOverrides=\"AND\">");
    for (Field field : PersistentUtil.getPersistentFields(type)) {
      sets.append(String.format(
              "<if test='includes.contains(\"%1$s\") and !excludes.contains(\"%1$s\")'> ",
              field.getName()
      ));
      // columnName = #{ }

      sets.append("and ");
      sets.append(PersistentUtil.getColumnName(field)).append(" = ")
              .append(ColumnMetaResolver.resolveSqlPlaceholder(field, Constant.CERTAINTY_ENTITY_KEY));

      sets.append("</if> ");
    }

    sets.append("</trim> ");

    return sets.toString();
  }




  public boolean inNeFeildArr(String fieldName) {
    if(neFeildArr!=null && neFeildArr.length>0){
      return JpaTools.contains(neFeildArr,fieldName);
    }
    return false;
  }

  public boolean inLikeFeildArr(String fieldName) {
    if(likeFeildArr!=null && likeFeildArr.length>0){
      return JpaTools.contains(likeFeildArr,fieldName);
    }
    return false;
  }
  public boolean inEmptyEqFeildArr(String fieldName) {
    if(emptyEqFeildArr!=null && emptyEqFeildArr.length>0){
      return JpaTools.contains(emptyEqFeildArr,fieldName);
    }
    return false;
  }


  public boolean inDateParm(String fieldName) {
    if(dateParmArr!=null && dateParmArr.length>0){
      return JpaTools.contains(dateParmArr,fieldName);
    }
    return false;
  }

  public int indexOfDateParm(String fieldName) {
    if(dateParmArr!=null && dateParmArr.length>0){
      return ArrayUtils.indexOf(dateParmArr,fieldName);
    }
    return -1;
  }

  public String[] getDateSearchParm(int index) {
    String[] oneDateSearchArr =null;
    if(dateSearchArr!=null && dateSearchArr.length>index){
      return dateSearchArr[index].split(",");
    }
    oneDateSearchArr = new String[]{"bdate","edate"};
    return oneDateSearchArr;
  }

}
